#ifndef __STACK_H__
#define __STACK_H__

/*
===============================================================================

Stack template

===============================================================================
*/

namespace inf {

    template< typename Type >
    class Stack {
    public:
        typedef Type    value_type;
        typedef const Type const_value_type;
        typedef Type&   reference;
        typedef const Type& const_reference;

        bool			empty( void ) const;
        size_t          total_size( void ) const;
        int				size( void ) const;

        Type&			push( void );
        Type&			push( const Type& element );
        void			pop( void );
        Type&			top( void );
        const Type&		top( void ) const;

        void			clear( void );
        void			set_granularity( int newGranularity );

        void			swap( Stack& rhs );
    private:
        List< Type > stack;
    };

    template< typename Type >
    Type& Stack< Type >::push( void ) {
        return stack.alloc_to_back();
    }

    template< typename Type >
    Type& Stack< Type >::push( const Type& element ) {
        Type& ref = stack.alloc_to_back();
        ref = element;
        return ref;
    }

    template< typename Type >
    void Stack< Type >::pop( void ) {
        stack.remove_index( size() - 1 );
    }

    template< typename Type >
    Type& Stack< Type >::top( void ) {
        return stack[ size() - 1 ];
    }

    template< typename Type >
    const Type& Stack< Type >::top( void ) const {
        return stack[ size() - 1 ];
    }

    template< typename Type >
    void Stack< Type >::clear( void ) {
        stack.clear();
    }

    template< typename Type >
    void Stack< Type >::set_granularity( int newGranularity ) {
        stack.set_granularity( newGranularity );
    }

    template< typename Type >
    bool Stack< Type >::empty( void ) const {
        return stack.size() == 0;
    }

    template< typename Type >
    size_t Stack< Type >::total_size( void ) const {
        return stack.total_size();
    }

    template< typename Type >
    int Stack< Type >::size( void ) const {
        return stack.size();
    }

    template< typename Type >
    void Stack< Type >::swap( Stack& rhs ) {
        stack.swap( rhs.stack );
    }

}   // ::inf

#endif /* !__STACK_H__ */
